#pragma once

#include <cstdint>
#include <sys/time.h>
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

inline double randseed() { 
  struct timeval tv; 
  gettimeofday(&tv, 0); 
  return tv.tv_usec; 
}

/*
 * Rdtsc() - This function returns the value of the time stamp counter
 *           on the current core
 */
inline uint64_t Rdtsc()
{
    uint32_t lo, hi;
    asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
    return (((uint64_t) hi << 32) | lo);
}

inline double get_now() { 
  struct timeval tv; 
  gettimeofday(&tv, 0); 
  return tv.tv_sec + tv.tv_usec / 1000000.0; 
} 

/*
 * MemUsage() - Reads memory usage from /proc file system
 */
size_t MemUsage() {
  FILE *fp = fopen("/proc/self/statm", "r");
  if(fp == nullptr) {
    fprintf(stderr, "Could not open /proc/self/statm to read memory usage\n");
    exit(1);
  }

  unsigned long unused;
  unsigned long rss;
  if (fscanf(fp, "%ld %ld %ld %ld %ld %ld %ld", &unused, &rss, &unused, &unused, &unused, &unused, &unused) != 7) {
    perror("");
    exit(1);
  }

  (void)unused;
  fclose(fp);

  return rss * (4096 / 1024); // in KiB (not kB)
}

inline bool file_exist(const char *fname) {
    struct stat buffer;
    return (stat(fname, &buffer) == 0);
}

static constexpr char VALUE_POOL[] =
        "DNSKV_^dfh.pxrC6ZU79OnfCZ06DsNXWY3U4dt1JTGQVvylBdZSlHWXC4PokCxsMdjv8xRptFMMQyH12DEr7Zur"
        "tZpsyreMmPwuw7WMRnoN5wAYWtkqDwXyQlYb4RgtSc4xsonpTx2UhIUi15oJTx1CXAhmECacCQf4eeJ9Utus0N"
        "mKgEFV8qYDsNtJ21TkjCyCDhVIATkEugCw1BfNIB9AZDGiqXc0llp4rlJPl4bIG2QC4La3M1oh3yIGkolpdoYV"
        "er1dc9EfQz88q5Hv00g53Q3H6jcgicoY8YW5K4josd2e53ikesQi2kzqvTI9xxM5wtFexkFm8wFdTf37Hz204w"
        "fQErGZkdMnRxXJ5EJ627e7zuFuVtazb0L65B3nU5R9tyUl2bTZiDcakK9evrTXoTkbkGjkCOiMSTNCzlUZCxof"
        "jYQCLusRkXEm0CNVuifTnytctwLfKjwob4hJ0WxlQN9FV9Mm9zT61EQ8zEMrqr6hf7XMqhcQR7DWAKaspUaU6h"
        "oP2w3t3MktVaBp6MgS6Apbkb7EsihETHHqKFkKMCkYBbKfgsq7Jy49T1Wx2UJsD3XX03kVBbqRWmrjIKzqQEnN"
        "sd0f-0d09540936/.f/dfprjetroeijtte0985409609254fj/.s.1293@1!$43556oi5y6o54yi6ikjsdbfsd"
        ")(*7^hdjdyf484*^%$$3{}}{}{POI)_IUOHH&*^^&$Dydyutd65456djug(*_(*OIHJHKJBKJBKJB@A@A$gggg"
        "+_0-8435906IYWV79364ngkbo5m788*()M<:>><:Lpkdfgmgrtjyoyij5yj657i6509ju560ju560ju0uj0uj6"
        "NvhE8N7yR26fgHncH6QbsI10HyxlvYHKFiMk5nPNDbffueF2xKLzteSd0NazU2APkJWXvBW2oUu8dkZnWMM8TH"
        "vrUoLDWwMdh14MfxwmEQbtGnUHEpRktUB6b7JTJN8IHyxlvYHKFiMk5nPND()bueF2xKLz;|@f,t";

std::string GenerateValue(uint64_t k, int length) {
    std::string result = std::to_string(k);

    length -= result.size();
    int cur_length = 0;
    while(cur_length < length) {
        int cut_len = std::min(size_t(length - cur_length), sizeof(VALUE_POOL));
        result.append(std::string(VALUE_POOL, cut_len));
        cur_length += cut_len;
    }

    return result;
}